package com.yb.guigu.pick.minio.upload.client;

import com.yb.guigu.pick.core.exception.GuiguBusinessException;
import com.yb.guigu.pick.minio.upload.bean.MinioProperties;
import com.yb.guigu.pick.upload.bean.MergeRequest;
import com.yb.guigu.pick.upload.bean.PutRequest;
import com.yb.guigu.pick.upload.bean.UploadRequest;
import com.yb.guigu.pick.upload.bean.UploadResponse;
import com.yb.guigu.pick.upload.client.UploadClient;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Copyright (C), 2022-2023, 姚兵
 * Author: 32210
 * Date: 2023/5/11 11:32
 * FileName: MinioUploadClient
 * Description:
 */

@Slf4j
public class MinioUploadClient implements UploadClient {

    MinioClient minioClient;

    MinioProperties minioProperties;

    public MinioUploadClient(MinioProperties minioProperties,MinioClient minioClient){

        this.minioProperties=minioProperties;
        this.minioClient=minioClient;
    }

    @Override
    public UploadResponse upload(UploadRequest uploadRequest) {

        try {
            ObjectWriteResponse response = minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(uploadRequest.getBucket())
                            .object(uploadRequest.getRemoteFilepath())
                            .contentType(uploadRequest.getContentType())
                            .filename(uploadRequest.getLocalFilepath())
                            .build());
            return new UploadResponse().setSuccess(true);
        } catch (Exception e) {
            log.info("upload error:{}",e);
            throw new GuiguBusinessException(e.getMessage());
        }
    }

    @Override
    public UploadResponse put(PutRequest putRequest) {
        try {
            ObjectWriteResponse response = minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(putRequest.getBucket())
                            .object(putRequest.getRemoteFilepath())
                            .contentType(putRequest.getContentType())
                            .stream(putRequest.getUploadStream(),putRequest.getUploadStream().available(),-1)
                            .build());
            return new UploadResponse().setSuccess(true);
        } catch (Exception e) {
            log.info("upload error:{}",e);
            throw new GuiguBusinessException(e.getMessage());
        }
    }

    @Override
    public UploadResponse merge(MergeRequest mergeRequest) {

        List<MergeRequest.ComposeFile> composeFiles = mergeRequest.getComposeFiles();

        List<ComposeSource> sources = composeFiles.stream()
                .map(composeFile ->
                        ComposeSource.builder()
                                .bucket(composeFile.getBucket())
                                .object(composeFile.getRemoteFilepath())
                                .build()).collect(Collectors.toList());

        try {
            minioClient.composeObject(ComposeObjectArgs.builder()
                    .sources(sources)
                    .bucket(mergeRequest.getBucket())
                    .object(mergeRequest.getRemoteFilepath())
                    .build());


            List<DeleteObject> deleteObjects = composeFiles.stream().map(composeFile -> {
                return new DeleteObject(composeFile.getRemoteFilepath());
            }).collect(Collectors.toList());
            //合并完成删除文件
            Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder()
                    .bucket(mergeRequest.getBucket())
                    .objects(deleteObjects)
                    .build());
            results.forEach(deleteErrorResult -> {
                log.info("{}",deleteErrorResult);
            });

            return new UploadResponse().setSuccess(true);
        } catch (Exception e) {
            log.info("upload error:{}",e);
            throw new GuiguBusinessException(e.getMessage());
        }
    }
}
